home *** CD-ROM | disk | FTP | other *** search
- /*
- SNEWS 1.91
-
- active - routines to manipulate the active, .nrc and .rc files
-
-
- Copyright (C) 1991 John McCombs, Christchurch, NEW ZEALAND
- john@ahuriri.gen.nz
- PO Box 2708, Christchurch, NEW ZEALAND
-
- Modifications copyright (C) 1993 Daniel Fandrich
- <dan@fch.wimsey.bc.ca> or CompuServe 72365,306
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License, version 1, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- See the file COPYING, which contains a copy of the GNU General
- Public License.
-
-
- Source is formatted with a tab size of 4.
-
- */
-
- #define ACTIVE_C
-
- #include "defs.h"
- #include <alloc.h>
- #include <ctype.h>
-
- extern INFO my_stuff;
-
- int headf = BLACK;
- int headb = LIGHTGRAY;
-
- int textf = LIGHTGRAY;
- int textb = BLACK;
-
- int helpf = LIGHTGRAY;
- int helpb = BLACK;
-
- int msgf = BLACK;
- int msgb = LIGHTGRAY;
-
- volatile int break_hit = 0; /* incremented when control-break is hit */
-
- /*
- * These private variables are used to do all the i/o on the active
- * file.
- */
- static FILE *active_file;
-
- static ACTIVE *local_head;
-
-
- /*--------------------------- load the active file --------------------------*/
- ACTIVE *load_active_file(void)
- {
- /*
- * This routine opens the active file. It reads the data, allocating
- * ACTIVE elements in a linked list. Returns a pointer to the head of
- * the linked list.
- */
- char fn[80], buf[81];
- char *p;
- ACTIVE *this = NULL, *head = NULL;
- long posn = 0;
- int ct = 0;
- int ct_gp = 0;
-
- /* open the file */
- strcpy(fn, my_stuff.news_dir);
- strcat(fn, "active");
- if ((active_file = fopen(fn, "r+b")) == NULL) {
- fprintf(stderr, "cannot open %s\n", fn);
- exit(1);
- }
-
- /* read and store */
- while (fgets(buf, 80, active_file) != NULL) {
-
- /* exit on ^Z on column 1 */
- if (buf[0] == '\x1A')
- break;
-
- ct++;
-
- if (strlen(buf) > 0) {
-
- if (head == NULL) {
- head = this = xmalloc(sizeof (ACTIVE));
- head->last = NULL;
- head->index = ct_gp;
- } else {
- ct_gp++;
- this->next = xmalloc(sizeof (ACTIVE));
- this->next->last = this;
- this = this->next;
- this->index = ct_gp;
- }
-
- if ((this) == NULL) {
- fprintf(stderr, "cannot allocate memory for active list\n");
- exit(1);
- }
-
-
- if ((p = strtok(buf, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d #1\n", ct);
- exit(1);
- }
- strcpy(this->group, p);
- this->local = isupper(this->group[0]); /* is group local? */
- this->group[0] = tolower(this->group[0]);
-
- if ((p = strtok(NULL, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d #2\n", ct);
- exit(1);
- }
- strcpy(this->gp_file, p);
-
- if ((p = strtok(NULL, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d #3\n", ct);
- exit(1);
- }
- this->lo_num = atol(p);
-
- if ((p = strtok(NULL, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d #4\n", ct);
- exit(1);
- }
- this->hi_num = atol(p);
-
- if ((p = strtok(NULL, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d #5\n", ct);
- exit(1);
- }
- this->post = tolower(*p);
-
- this->num_pos = posn;
- this->read_list = NULL;
- }
-
- posn = ftell(active_file);
- }
-
- if (this)
- this->next = NULL;
-
- local_head = head;
-
- return(head);
- }
-
-
-
-
- /*------------------------- close the active file ---------------------------*/
- void close_active_file(void)
- {
- /*
- * Close the active file and deallocate the linked list
- */
-
- ACTIVE *this;
-
- this = local_head;
-
- while (this != NULL) {
- local_head = this;
- this = this->next;
- free(local_head);
- }
-
- fclose(active_file);
-
- }
-
-
- /*------------------------- close the active file ---------------------------*/
- void close_active(void)
- {
- /*
- * Close the active file
- */
-
-
- fclose(active_file);
-
- }
-
-
-
- /*------------------------- check group in post list -------------------------*/
- int check_valid_post_group(char *ng)
- {
- /*
- * Check a string as a valid newsgroup name. Returns TRUE if found and
- * posting is allowed.
- *
- * Note: this should be changed to return 1 if posting is allowed,
- * 0 if it is not, and -1 if the group is moderated.
- */
-
- ACTIVE *this = local_head;
-
- while (this != NULL) {
- if (strcmp(ng, this->group) == 0)
- switch (this->post) {
- case 'y': return TRUE;
- /* case 'm': return -1; */
- case 'n':
- default: return FALSE;
- }
- this = this->next;
- }
-
- return (FALSE);
- }
-
-
- /*-------------------- see if newsgroup is local only -----------------------*/
- int is_local_group(char *ng)
- {
- ACTIVE *this = local_head;
-
- while (this != NULL) {
- if (strcmp(ng, this->group) == 0)
- return(this->local);
- this = this->next;
- }
-
- return (TRUE); /* return TRUE if group name is not found */
- }
-
-
-
- /*-------------------- find a newsgroup in active list ----------------------*/
- ACTIVE *find_news_group(char *group)
- {
- /*
- * This routine searches the active structure for the specified
- * newsgroup, and returns a pointer to the entry, or to group
- * junk if not found. The search for junk is made via a recursive
- * call. Fatal if junk not found
- */
-
- ACTIVE *this;
-
- this = local_head;
-
- while ((this != NULL) && (stricmp(group, this->group) != 0)) {
- this = this->next;
- }
- if (this == NULL) {
- if (stricmp(group, "junk") != 0) {
- this = find_news_group("junk");
- } else {
- fprintf(stderr, "active file must have newsgroup junk\n");
- exit(1);
- }
- }
- return(this);
- }
-
-
-
-
- /*-------------------------- update active file ---------------------------*/
- void update_active_entry(ACTIVE *a)
- {
- /*
- * This routine takes a pointer to an active entry and updates
- * its data on disk
- */
-
- char buf[(ACTIVE_NUM_LEN*2) + 2];
- int n;
- long where;
-
- sprintf(buf, "%08ld %08ld", a->lo_num, a->hi_num);
-
- n = (ACTIVE_NUM_LEN*2) + 1;
- where = a->num_pos + strlen(a->group) + 1 + strlen(a->gp_file) + 1;
- fseek(active_file, where, SEEK_SET);
- if (fwrite(buf, 1, n, active_file) != n) {
- fprintf(stderr, "active file update failed for %s\n", a->group);
- exit(1);
- }
-
- fflush(active_file);
- }
-
-
-
-
-
- /*------------------- make newsgroup name and directory --------------------*/
- char *make_news_group_name(char *ng)
- {
- /*
- * This routine takes the newsgroup name, replaces the '.' with
- * '\' and creates the directory if none exists. The returned name
- * has a trailing '\'
- */
-
- static char fn[512];
- ACTIVE *tmp;
-
-
- tmp = find_news_group(ng);
-
- sprintf(fn, "%snewsbase\\%s", my_stuff.news_dir, tmp->gp_file);
-
- return(&fn[0]);
- }
-
-
-
-
-
- /*-------------------------- save the seen list -------------------------*/
- void load_read_list(void)
- {
- /*
- * Load the user's list of seen articles
- */
-
- FILE *tmp_file;
- ACTIVE *act;
- int i, continue_flag;
- int articles;
- char *a, buf[256], *p, real_name[80];
-
- /* allocate the arrays and set to unread, ie FALSE */
- act = local_head;
- while (act != NULL) {
-
- articles = (int)(act->hi_num - act->lo_num);
- if (articles > 0) {
- a = act->read_list = xmalloc(articles * sizeof(char));
- for (i = 0; i < articles; i++) {
- *(a+i) = FALSE;
- }
- } else {
- act->read_list = NULL;
- }
- act = act->next;
- }
-
- /* read and process the file - if not present, just carry on */
- /* strcpy(buf, my_stuff.news_dir);
- strcat(buf, my_stuff.user);
- strcat(buf, ".nrc");
- */
- strcat(strcpy(buf, my_stuff.home), "snews.nrc");
- if ((tmp_file = fopen(buf, "rt")) != NULL) {
-
- continue_flag = FALSE;
- while (fgets(buf, 255, tmp_file) != NULL) {
-
- p = strtok(buf, " \n\r");
-
- if (!continue_flag) {
-
- strcpy(real_name, p);
- act = find_news_group(p);
- articles = (int)(act->hi_num - act->lo_num);
-
- /* if no articles or unknown group eat the rest */
- p = strtok(NULL, " \n\r");
-
- }
-
- /* scan the rest of the line getting numbers and setting flags */
- continue_flag = FALSE;
- while (p != NULL) {
-
- /* check for continuation backslash */
- if (*p != '\\') {
- i = (int) (atol(p) - (act->lo_num + 1));
- if ((i >= 0) && (i < articles) &&
- ((stricmp(act->group, "junk") != 0) ||
- (stricmp(real_name, "junk") == 0))) {
- *((act->read_list)+i) = TRUE;
- }
- } else {
- continue_flag = TRUE;
- break;
- }
- p = strtok(NULL, " \n\r");
- }
- }
-
- fclose(tmp_file);
- }
- }
-
-
-
-
-
- /*-------------------------- load the seen list -------------------------*/
- void save_read_list(void)
- {
- /*
- * Save the user's list of read articles and deallocate storage
- */
-
-
- FILE *tmp_file;
- ACTIVE *act;
- int i, articles, ct;
- char buf[256];
-
- /* open the file */
- /* strcpy(buf, my_stuff.news_dir);
- strcat(buf, my_stuff.user);
- strcat(buf, ".nrc");
- */
- strcat(strcpy(buf, my_stuff.home), "snews.nrc");
- if ((tmp_file = fopen(buf, "wt")) == NULL) {
- fprintf(stderr, "can't open user's rc file for output\n");
- exit(1);
- }
-
- /* write out the lists and deallocate the arrays */
- act = local_head;
- while (act != NULL) {
-
- articles = (int)(act->hi_num - act->lo_num);
- if (articles > 0) {
- fprintf(tmp_file, "%s ", act->group);
-
- ct = 0;
-
- if (act->read_list != NULL) {
- for (i = 0; i < articles; i++) {
- if(*((act->read_list)+i)) {
- ct++;
- fprintf(tmp_file, "%d ", i+act->lo_num+1);
- if ((ct % 10) == 0)
- fprintf(tmp_file, "\\ \n");
- }
- }
- }
-
- fprintf(tmp_file, "\n");
- if (act->read_list != NULL) {
- free(act->read_list);
- }
- }
- act = act->next;
- }
-
- fclose(tmp_file);
-
- }
-
- /*------------------------- set colors -----------------------------------*/
-
- void set_colors(char *keyword, char *value)
- {
- static char *colors[] = {"bla","blu","gre","cya","red","mag","yel","whi"};
- int color = 0,
- i = 0;
- char *f = NULL;
-
- if (value)
- strlwr(value);
-
- f = strtok(value,"\0"); /* does this do anything? [df] */
-
- while (isspace(*f)) f++;
-
- for (i = 0; (i < 8) && (strncmp(colors[i],f,3) != 0); i++)
- /* empty loop */ ;
-
- color = (i < 8) ? i : 0;
- color |= (strchr(f, '+') != NULL) ? 8 : 0;
-
- helpf = (strncmp("helpf", keyword, 5)) ? helpf : (unsigned char) color;
- helpb = (strncmp("helpb", keyword, 5)) ? helpb : (unsigned char) color;
-
- textf = (strncmp("textf", keyword, 5)) ? textf : (unsigned char) color;
- textb = (strncmp("textb", keyword, 5)) ? textb : (unsigned char) color;
-
- headf = (strncmp("headf", keyword, 5)) ? headf : (unsigned char) color;
- headb = (strncmp("headb", keyword, 5)) ? headb : (unsigned char) color;
-
- msgf = (strncmp("msgf", keyword, 4)) ? msgf : (unsigned char) color;
- msgb = (strncmp("msgb", keyword, 4)) ? msgb : (unsigned char) color;
- }
-
-
-
- /*------------------------- load UUPC rc files ---------------------------*/
-
- int load_stuff(void)
- {
- /*
- * Trawl the UUPC files to get the stuff we need - return TRUE
- * if completed ok
- */
-
- int res = 0;
- int i;
- char buf[256];
- char *fn, *p, *v;
- FILE *tmp;
-
- /* news base directory */
-
- if ((fn = getenv("UUPCNEWS")) == NULL) {
- fprintf(stderr, "UUPCNEWS environment variable undefined");
- exit(1);
- }
-
- /* give it a trailing \ */
-
- strcpy(my_stuff.news_dir, fn);
- if (my_stuff.news_dir[ strlen(my_stuff.news_dir)-1 ] != '\\')
- strcat(my_stuff.news_dir, "\\");
-
- /* set other defaults */
- strcpy(my_stuff.replyuser, "-none-");
- strcpy(my_stuff.uncompress, "compress -d %s");
- my_stuff.home[0] = '\0';
- my_stuff.signature[0] = '\0';
- my_stuff.my_organisation[0] = '\0';
- my_stuff.alias_file[0] = '\0';
- strcpy(my_stuff.extract_file, "extract.nws");
- strcpy(my_stuff.hotpipe, "metamail %s");
- if ((v = getenv("EDITOR")) == NULL)
- strcpy(my_stuff.editor, "edit %s");
- else
- strcat(strcpy(my_stuff.editor, v), " %s");
-
- /* get the temporary directory string from the environment in case
- it isn't in the configuration file */
- if (((v = getenv("TEMP")) != NULL) ||
- ((v = getenv("TMP")) != NULL))
- strcpy(my_stuff.temp_str, v);
- else
- my_stuff.temp_str[0] = '\0';
- strcat(strcpy(my_stuff.temp_name, my_stuff.temp_str), "$unbatch");
-
- /* read the system file first, then the user's personal file */
-
- for (i = 0; i < 2; i++) {
-
- /* choose the file to open */
-
- if (i == 0) {
- fn = getenv("SNEWSRC");
- if (fn == NULL) {
- fn = getenv("UUPCUSRRC");
- if (fn == NULL) {
- fprintf(stderr, "Enviroment variable SNEWSRC not defined\n");
- }
- }
- }
- else {
- fn = getenv("UUPCSYSRC");
- if (fn == NULL) {
- fprintf(stderr, "Enviroment variable UUPCSYSRC not defined\n");
- }
- }
-
- if ((tmp = fopen(fn, "rt")) != NULL) {
-
- /* read a line from the configuration file */
- while (fgets(buf, 255, tmp)) {
-
- if (((p = strtok(buf, " =\r\n")) != NULL) && (*p != '#')) {
- v = strtok(NULL, " =\r\n");
-
- if (stricmp(p, "mailserv") == 0) {
- strcpy(my_stuff.mail_server, v);
- res++;
- }
- if (strnicmp(p, "color", 5) == 0) {
- set_colors(p+5, v);
- }
- if (stricmp(p, "nodename") == 0) {
- strcpy(my_stuff.my_site, v);
- res++;
- }
- if (stricmp(p, "newsdir") == 0) {
- strcpy(my_stuff.incoming_dir, v);
- if ((my_stuff.incoming_dir[strlen(my_stuff.incoming_dir)-1] != '/') &&
- (my_stuff.incoming_dir[strlen(my_stuff.incoming_dir)-1] != '\\'))
- strcat(my_stuff.incoming_dir, "/");
- expand_filename(my_stuff.incoming_dir);
- res++;
- }
- if (stricmp(p, "domain") == 0) {
- strcpy(my_stuff.my_domain, v);
- res++;
- }
- if (stricmp(p, "tempdir") == 0) {
- strcpy(my_stuff.temp_str, v);
- /* temp_str must end with \ and can't have any / because DOS doesn't like
- those for redirection in a system() line
- First do a very ugly kludge to see if we're operating on a system that
- uses / instead of \
- (note to self: don't be so lazy and look up the switchar system call! */
- if (getenv("COMSPEC")[2] != '/') {
- while (strchr(my_stuff.temp_str, '/'))
- *strchr(my_stuff.temp_str, '/') = '\\';
- if (my_stuff.temp_str[strlen(my_stuff.temp_str)-1] != '\\')
- strcat(my_stuff.temp_str, "\\");
- }
- expand_filename(my_stuff.temp_str);
- /* temporary unbatch file name -- can't have extension */
- strcpy(my_stuff.temp_name, my_stuff.temp_str);
- strcat(my_stuff.temp_name, "$unbatch");
- }
- if (stricmp(p, "mailbox") == 0) {
- strcpy(my_stuff.user, v);
- res++;
- }
- if (stricmp(p, "Signature") == 0) {
- strcpy(my_stuff.signature, v);
- expand_filename(my_stuff.signature);
- }
- if (stricmp(p, "name") == 0) {
- strcpy(my_stuff.my_name, v);
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.my_name, " ");
- strcat(my_stuff.my_name, v);
- v = strtok(NULL, " =\r\n");
- }
- res++;
- }
- if (stricmp(p, "Organization") == 0) {
- strcpy(my_stuff.my_organisation, v);
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.my_organisation, " ");
- strcat(my_stuff.my_organisation, v);
- v = strtok(NULL, " =\r\n");
- }
- }
-
- if (stricmp(p, "Replyto") == 0) {
- strcpy(my_stuff.replyuser, v);
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.replyuser, " ");
- strcat(my_stuff.replyuser, v);
- v = strtok(NULL, " =\r\n");
- }
- }
-
- if (stricmp(p, "Editor") == 0) {
- strcpy(my_stuff.editor, v);
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.editor, " ");
- strcat(my_stuff.editor, v);
- v = strtok(NULL, " =\r\n");
- }
- expand_filename(my_stuff.editor);
- }
- if (stricmp(p, "Uncompress") == 0) {
- strcpy(my_stuff.uncompress, v);
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.uncompress, " ");
- strcat(my_stuff.uncompress, v);
- v = strtok(NULL, " =\r\n");
- }
- expand_filename(my_stuff.uncompress);
- }
- if (stricmp(p, "HotPipe") == 0) {
- strcpy(my_stuff.hotpipe, v);
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.hotpipe, " ");
- strcat(my_stuff.hotpipe, v);
- v = strtok(NULL, " =\r\n");
- }
- expand_filename(my_stuff.hotpipe);
- }
- if (stricmp(p, "Home") == 0) {
- strcpy(my_stuff.home, v);
- if (my_stuff.home[ strlen(my_stuff.home)-1 ] != '\\')
- strcat(my_stuff.home, "/");
- res++;
- }
- if (stricmp(p, "Aliases") == 0) {
- strcpy(my_stuff.alias_file, v);
- expand_filename(my_stuff.alias_file);
- }
- if (stricmp(p, "Extract") == 0) {
- strcpy(my_stuff.extract_file, v);
- expand_filename(my_stuff.extract_file);
- }
- } /* if */
- } /* while */
- fclose (tmp);
-
- }
- else {
- fprintf(stderr, "Cannot open %s\n", fn);
- }
- }
- return(res >= 7); /* see if all mandatory items have been specified */
- }
-
-
-
- /*--------------------------- unpack the batch ------------------------*/
- FILE *open_out_file(char *ng)
- {
- /*
- * This routine creates a filename from the newsgroup name.
- * The active file counter are updated.
- */
-
- ACTIVE *gp;
- char *fn;
- FILE *tmp;
-
- gp = find_news_group(ng);
-
- fn = make_news_group_name(gp->group);
-
- (gp->hi_num)++;
- update_active_entry(gp);
-
- if ((tmp = flockopen(fn, "r+b")) == NULL) {
- fprintf(stderr,"active: cannot open text file %s\n", fn);
- exit(1);
- }
- fseek(tmp, 0, SEEK_END);
-
- return(tmp);
- }
-
-
- /*--------------------------- unpack the batch ------------------------*/
- FILE *open_index_file(char *ng)
- {
- /*
- * This routine open the index file for the newsgroup
- */
-
- ACTIVE *gp;
- char fnx[256], *fn;
- FILE *tmp;
-
- /* printf("news: ng found = %s\n", ng); */
- gp = find_news_group(ng);
- fn = make_news_group_name(gp->group);
- sprintf(fnx, "%s.IDX", fn);
-
- if((tmp = flockopen(fnx, "r+b")) == NULL) {
- fprintf(stderr, "active: cannot open index file %s\n", fn);
- exit(1);
- }
- fseek(tmp, 0, SEEK_END);
-
- return(tmp);
-
- }
-
-
-
- /*------------------------- post sequence number ----------------------------*/
- int post_sequence(void)
- {
- /*
- * Get the sequence number from the seq file if it exists - if
- * not create it
- */
-
- FILE *seq_file;
- char fn[256];
- int seq;
-
- strcpy(fn, my_stuff.news_dir);
- strcat(fn, "nseq");
-
- if ((seq_file = flockopen(fn, "r+t")) != NULL) {
- fscanf(seq_file, "%d", &seq);
- seq++;
- rewind(seq_file);
- } else {
- seq = 0;
- seq_file = flockopen(fn, "wt");
- }
-
- fprintf(seq_file, "%d", seq);
-
- fclose(seq_file);
- return(seq);
- }
-
-
- /*-------------------------------- safeish malloc --------------------------*/
- void *xmalloc(size_t size)
- {
- void *p;
- if ((p = malloc(size)) == NULL) {
- gotoxy(1,25);
- fprintf(stderr, "\n\nSORRY - NO MEMORY LEFT \n");
- exit(1);
- }
-
- return(p);
- }
-
-
- /*------------------------ ctrl-break signal handler -----------------------*/
- void cdecl sig_break()
- {
- signal(SIGINT, sig_break); /* reactive signal */
- ++break_hit; /* indicate that control-break was hit */
- }
-
-
- /*------------------------- expand ~/ in file name -------------------------*/
- char *expand_filename(char *fn)
- {
- /* if file name starts with ~/ change to user's home directory */
- if ((fn[0] == '~') && ((fn[1] == '/') || (fn[1] == '\\')) && fn[2]) {
- memmove(fn+strlen(my_stuff.home), fn+2, strlen(fn+2) + 1);
- memmove(fn, my_stuff.home, strlen(my_stuff.home));
- }
- return fn;
- }
-